home *** CD-ROM | disk | FTP | other *** search
/ GFX Sensations 1 / Graphic Sensations - Volume 1.iso / tools / amiga / 3d_tools / irit40s.lha / Irit / iritfltr / irit2ray.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-12-31  |  26.3 KB  |  904 lines

  1. /*****************************************************************************
  2. * Filter to convert IRIT data files to ray shade format.             *
  3. *                                         *
  4. * Written by:  Gershon Elber                Ver 1.0, Sep 1991    *
  5. *****************************************************************************/
  6.  
  7. #include <stdio.h>
  8. #include <math.h>
  9. #include <string.h>
  10. #include "irit_sm.h"
  11. #include "iritprsr.h"
  12. #include "allocate.h"
  13. #include "attribut.h"
  14. #include "iritgrap.h"
  15. #include "getarg.h"
  16. #include "genmat.h"
  17. #include "ffcnvrt.h"
  18. #include "ip_cnvrt.h"
  19.  
  20. #define DIST_EPSILON    2e-4
  21. #define SIZE_EPSILON    1e-5
  22.  
  23. #define DEFAULT_POLYLINE_WIDTH  0.05
  24.  
  25. #define CONE_SIZE    5e-4
  26.  
  27. #define MIN_RATIO    0.01
  28.  
  29. #ifdef NO_CONCAT_STR
  30. static char *VersionStr =
  31.     "Irit2Ray        Version 4.0,    Gershon Elber,\n\
  32.      (C) Copyright 1989/90/91/92/93 Gershon Elber, Non commercial use only.";
  33. #else
  34. static char *VersionStr = "Irit2Ray    " VERSION ",    Gershon Elber,    "
  35.     __DATE__ ",   " __TIME__ "\n" COPYRIGHT ", Non commercial use only.";
  36. #endif /* NO_CONCAT_STR */
  37.  
  38. static char
  39. #ifdef DOUBLE
  40.     *CtrlStr = "irit2ray l%- 4%- G%-GridSize!d f%-FineNess!d o%-OutName!s g%- p%-Zmin|Zmax!F!F P%- M%- T%- I%-#UIso[:#VIso]!s S%-#SampPerCrv!d z%- DFiles!*s";
  41. #else
  42.     *CtrlStr = "irit2ray l%- 4%- G%-GridSize!d f%-FineNess!d o%-OutName!s g%- p%-Zmin|Zmax!f!f P%- M%- T%- I%-#UIso[:#VIso]!s S%-#SampPerCrv!d z%- DFiles!*s";
  43. #endif /* DOUBLE */
  44.  
  45. static char
  46.     *GlblStrNumOfIsolines = NULL,
  47.     *GlblOutFileName = "irit2ray";
  48.  
  49. static int
  50.     GlblTalkative = FALSE,
  51.     GlblGridSize = 5,
  52.     GlblGridFlag = FALSE,
  53.     GlblFineNess = 5,
  54.     GlblDrawMesh = 5,
  55.     GlblDumpOnlyGeometry = FALSE,
  56.     GlblDumpPolylines = FALSE,
  57.     GlblDumpObjsAsPolylines = FALSE,
  58.     GlblFourPerFlat = FALSE,
  59.     GlblNumOfIsolines[2] = { IG_DEFAULT_NUM_OF_ISOLINES,
  60.                  IG_DEFAULT_NUM_OF_ISOLINES },
  61.     GlblSamplesPerCurve = IG_DEFAULT_SAMPLES_PER_CURVE;
  62.  
  63. static RealType
  64.     GlblZBBox[2] = { INFINITY, -INFINITY },
  65.     GlblPolylineDepthCue[3];
  66.  
  67. static MatrixType CrntViewMat;            /* This is the current view! */
  68.  
  69. static int TransColorTable[][4] = {
  70.     { /* BLACK        */ 0,    0,   0,   0 },
  71.     { /* BLUE        */ 1,    0,   0, 255 },
  72.     { /* GREEN        */ 2,    0, 255,   0 },
  73.     { /* CYAN        */ 3,    0, 255, 255 },
  74.     { /* RED        */ 4,  255,   0,   0 },
  75.     { /* MAGENTA     */ 5,  255,   0, 255 },
  76.     { /* BROWN        */ 6,   50,   0,   0 },
  77.     { /* LIGHTGRAY    */ 7,  127, 127, 127 },
  78.     { /* DARKGRAY    */ 8,   63,  63,  63 },
  79.     { /* LIGHTBLUE    */ 9,    0,   0, 255 },
  80.     { /* LIGHTGREEN    */ 10,   0, 255,   0 },
  81.     { /* LIGHTCYAN    */ 11,   0, 255, 255 },
  82.     { /* LIGHTRED    */ 12, 255,   0,   0 },
  83.     { /* LIGHTMAGENTA    */ 13, 255,   0, 255 },
  84.     { /* YELLOW        */ 14, 255, 255,   0 },
  85.     { /* WHITE        */ 15, 255, 255, 255 },
  86.     { /* BROWN        */ 20,  50,   0,   0 },
  87.     { /* DARKGRAY    */ 56,  63,  63,  63 },
  88.     { /* LIGHTBLUE    */ 57,   0,   0, 255 },
  89.     { /* LIGHTGREEN    */ 58,   0, 255,   0 },
  90.     { /* LIGHTCYAN    */ 59,   0, 255, 255 },
  91.     { /* LIGHTRED    */ 60, 255,   0,   0 },
  92.     { /* LIGHTMAGENTA    */ 61, 255,   0, 255 },
  93.     { /* YELLOW        */ 62, 255, 255,   0 },
  94.     { /* WHITE        */ 63, 255, 255, 255 },
  95.     {               -1,   0,   0,   0 }
  96. };
  97.  
  98. static void DumpDataForRayShade(IPObjectStruct *PObjects);
  99. static int DumpOneObject(FILE *FRay, FILE *FGeom, IPObjectStruct *PObject);
  100. static int DumpOnePoly(FILE *FGeom, IPPolygonStruct *PPoly,
  101.                IPObjectStruct *PObj, char *Name, RealType Width);
  102. static int DumpOnePolygon(FILE *f, IPPolygonStruct *PPolygon, char *Name);
  103. static int DumpOnePolyline(FILE *f, IPPolygonStruct *PPolyline, char *Name,
  104.                         RealType Width, int IsPolyline);
  105. static void DumpCone(RealType R1, RealType X1, RealType Y1, RealType Z1,
  106.              RealType R2, RealType X2, RealType Y2, RealType Z2,
  107.              FILE *FGeom, char *Name);
  108. static RealType *MapPoint(RealType *Pt);
  109. static RealType *MapVector(RealType *Pt, RealType *Vec);
  110. static void Irit2RayExit(int ExitCode);
  111.  
  112. /*****************************************************************************
  113. * Main routine - Read Parameter    line and do what you need...             *
  114. *****************************************************************************/
  115. void main(int argc, char **argv)
  116. {
  117.     int Error,
  118.     FineNessFlag = FALSE,
  119.     LinearOnePolyFlag = FALSE,
  120.     VerFlag = FALSE,
  121.     OutFileFlag = FALSE,
  122.     SamplesPerCurveFlag = FALSE,
  123.     NumOfIsolinesFlag = FALSE,
  124.     NumFiles = 0;
  125.     char Line[LINE_LEN_LONG], *p,
  126.     **FileNames = NULL;
  127.     IPObjectStruct *PObjects;
  128.  
  129.     if ((Error = GAGetArgs(argc, argv, CtrlStr, &LinearOnePolyFlag,
  130.                &GlblFourPerFlat, &GlblGridFlag, &GlblGridSize,
  131.                &FineNessFlag, &GlblFineNess,  &OutFileFlag,
  132.                &GlblOutFileName, &GlblDumpOnlyGeometry,
  133.                &GlblDumpPolylines, &GlblPolylineDepthCue[0],
  134.                &GlblPolylineDepthCue[1], &GlblDumpObjsAsPolylines,
  135.                &GlblDrawMesh, &GlblTalkative,
  136.                &NumOfIsolinesFlag, &GlblStrNumOfIsolines,
  137.                &SamplesPerCurveFlag, &GlblSamplesPerCurve,
  138.                &VerFlag, &NumFiles, &FileNames)) != 0) {
  139.     GAPrintErrMsg(Error);
  140.     GAPrintHowTo(CtrlStr);
  141.     Irit2RayExit(1);
  142.     }
  143.  
  144.     if (VerFlag) {
  145.     fprintf(stderr, "\n%s\n\n", VersionStr);
  146.     GAPrintHowTo(CtrlStr);
  147.     Irit2RayExit(0);
  148.     }
  149.  
  150.     if (GlblDumpPolylines) {
  151.     if (APX_EQ(GlblPolylineDepthCue[0], GlblPolylineDepthCue[1])) {
  152.         fprintf(stderr, "Cannot compute depth cue if Zmin == Zmax\n");
  153.         Irit2RayExit(1);
  154.     }
  155.     else {
  156.         /* Precompute DZ. */
  157.         GlblPolylineDepthCue[2] =
  158.         GlblPolylineDepthCue[1] - GlblPolylineDepthCue[0]; 
  159.     }
  160.     }
  161.  
  162.     if (LinearOnePolyFlag) {
  163.     fprintf(stderr, "Linear patch side will have a single polygon.\n");
  164.     CagdSetLinear2Poly(CAGD_ONE_POLY_PER_COLIN);
  165.     }
  166.     else
  167.         CagdSetLinear2Poly(CAGD_REG_POLY_PER_LIN);
  168.  
  169.     if (NumOfIsolinesFlag && GlblStrNumOfIsolines != NULL) {
  170.     if (sscanf(GlblStrNumOfIsolines, "%d:%d",
  171.            &GlblNumOfIsolines[0], &GlblNumOfIsolines[1]) != 2) {
  172.         if (sscanf(GlblStrNumOfIsolines, "%d",
  173.                &GlblNumOfIsolines[0]) != 1) {
  174.         fprintf(stderr,
  175.             "Number(s) of isolines (-I) cannot be parsed.\n");
  176.         GAPrintHowTo(CtrlStr);
  177.         Irit2RayExit(1);
  178.         }
  179.         else {
  180.         GlblNumOfIsolines[1] = GlblNumOfIsolines[0];
  181.         }
  182.     }
  183.     }
  184.  
  185.     fprintf(stderr, "%s triangles per flat will be created.\n",
  186.         GlblFourPerFlat ? "Four" : "Two");
  187.  
  188.     if (!NumFiles) {
  189.     fprintf(stderr, "No data file names were given, exit.\n");
  190.     GAPrintHowTo(CtrlStr);
  191.     Irit2RayExit(1);
  192.     }
  193.  
  194.     if (!OutFileFlag) {        /* Pick the first input name as output name. */
  195.     strcpy(Line, FileNames[0]);
  196.     if ((p = strrchr(Line, '.')) != NULL)        /* Remove old file type. */
  197.         *p = 0;
  198.     GlblOutFileName = IritStrdup(Line);
  199.     }
  200.  
  201.     /* Get the data files: */
  202.     if ((PObjects = IritPrsrGetDataFiles(FileNames, NumFiles, TRUE, FALSE)) ==
  203.                                     NULL)
  204.     Irit2RayExit(1);
  205.  
  206.     if (IritPrsrWasPrspMat)
  207.     MatMultTwo4by4(CrntViewMat, IritPrsrViewMat, IritPrsrPrspMat);
  208.     else
  209.     GEN_COPY(CrntViewMat, IritPrsrViewMat, sizeof(MatrixType));
  210.  
  211.     DumpDataForRayShade(PObjects);
  212.  
  213.     if (GlblDumpPolylines && GlblZBBox[0] < GlblZBBox[1])
  214.     fprintf(stderr, "Z depth cueing of polylines spans [%lf : %lf]\n",
  215.         GlblZBBox[0], GlblZBBox[1]);
  216.  
  217.     Irit2RayExit(0);
  218. }
  219.  
  220. /*****************************************************************************
  221. * Routine to convert all surfaces/curves into polygons/lines as follows:     *
  222. * Curves are converted to polylines and surfaces are converted to polygons,  *
  223. * or to polylines if GlblDumpObjsAsPolylines is set.                 *
  224. *****************************************************************************/
  225. IPObjectStruct *IritPrsrProcessFreeForm(IPObjectStruct *CrvObjs,
  226.                     IPObjectStruct *SrfObjs)
  227. {
  228.     int LocalFourPerFlat;
  229.     float RelativeFineNess;
  230.     CagdCrvStruct *Crv, *Crvs;
  231.     CagdSrfStruct *Srf, *Srfs;
  232.     IPObjectStruct *PObj;
  233.     IPPolygonStruct *PPolygon, *PPolygonTemp;
  234.  
  235.     if (CrvObjs == NULL && SrfObjs == NULL)
  236.     return NULL;
  237.  
  238.     if (CrvObjs) {
  239.     for (PObj = CrvObjs; PObj != NULL; PObj = PObj -> Pnext) {
  240.         if (GlblTalkative)
  241.         fprintf(stderr, "Processing curve object \"%s\"\n",
  242.             PObj -> Name);
  243.  
  244.         Crvs = PObj -> U.Crvs;
  245.  
  246.         /* Replace curves with polylines. */
  247.         PObj -> U.Pl = NULL;
  248.         PObj -> ObjType = IP_OBJ_POLY;
  249.         IP_SET_POLYLINE_OBJ(PObj);
  250.         for (Crv = Crvs; Crv != NULL; Crv = Crv -> Pnext) {
  251.         PPolygon = PPolygonTemp =
  252.             Curve2Polylines(Crv, TRUE, GlblDrawMesh,
  253.                               GlblSamplesPerCurve);
  254.         while (PPolygonTemp -> Pnext)
  255.             PPolygonTemp = PPolygonTemp -> Pnext;
  256.         PPolygonTemp -> Pnext = PObj -> U.Pl;
  257.         PObj -> U.Pl = PPolygon;
  258.         }
  259.     }
  260.     }
  261.  
  262.     if (GlblDumpObjsAsPolylines) {
  263.     if (SrfObjs) {
  264.         for (PObj = SrfObjs; PObj != NULL; PObj = PObj -> Pnext) {
  265.         if (GlblTalkative)
  266.             fprintf(stderr, "Processing surface object \"%s\"\n",
  267.                 PObj -> Name);
  268.  
  269.         Srfs = PObj -> U.Srfs;
  270.  
  271.         /* Replace surfaces with polylines. */
  272.         PObj -> U.Pl = NULL;
  273.         PObj -> ObjType = IP_OBJ_POLY;
  274.         IP_SET_POLYLINE_OBJ(PObj);
  275.         for (Srf = Srfs; Srf != NULL; Srf = Srf -> Pnext) {
  276.             PPolygon = PPolygonTemp =
  277.             Surface2Polylines(Srf, TRUE, GlblDrawMesh,
  278.                       GlblNumOfIsolines,
  279.                       GlblSamplesPerCurve);
  280.             while (PPolygonTemp -> Pnext)
  281.             PPolygonTemp = PPolygonTemp -> Pnext;
  282.             PPolygonTemp -> Pnext = PObj -> U.Pl;
  283.             PObj -> U.Pl = PPolygon;
  284.         }
  285.         }
  286.     }
  287.     }
  288.     else {
  289.     if (SrfObjs) {
  290.         for (PObj = SrfObjs; PObj != NULL; PObj = PObj -> Pnext) {
  291.         CagdBBoxStruct BBox, TempBBox;
  292.         char GridStr[LINE_LEN];
  293.  
  294.         if (GlblTalkative)
  295.             fprintf(stderr, "Processing surface object \"%s\"\n",
  296.                 PObj -> Name);
  297.  
  298.         Srfs = PObj -> U.Srfs;
  299.         PObj -> U.Pl = NULL;
  300.         PObj -> ObjType = IP_OBJ_POLY;
  301.         IP_SET_POLYGON_OBJ(PObj);
  302.  
  303.         LocalFourPerFlat = GlblFourPerFlat;
  304.         
  305.         if (AttrGetObjectStrAttrib(PObj, "twoperflat"))
  306.             LocalFourPerFlat = FALSE;
  307.         if (AttrGetObjectStrAttrib(PObj, "fourperflat"))
  308.             LocalFourPerFlat = TRUE;
  309.         
  310.         if ((RelativeFineNess = AttrGetObjectRealAttrib(PObj,
  311.                     "resolution")) > IP_ATTR_BAD_REAL)
  312.             RelativeFineNess = 1.0;
  313.         
  314.         for (Srf = Srfs; Srf != NULL; Srf = Srf -> Pnext) {
  315.             if (GlblGridFlag) {
  316.             /* Generate bounding box to surfaces and estimate */
  317.             /* the grid size for it using GlblGridSize.      */
  318.             if (Srf == Srfs)
  319.                 CagdSrfBBox(Srf, &BBox);
  320.             else {
  321.                 CagdSrfBBox(Srf, &TempBBox);
  322.                 CagdMergeBBox(&BBox, &TempBBox);
  323.             }
  324.             }
  325.             PPolygon = PPolygonTemp =
  326.             IritSurface2Polygons(Srf, LocalFourPerFlat,
  327.                   (int) (RelativeFineNess * GlblFineNess), FALSE);
  328.             while (PPolygonTemp -> Pnext)
  329.             PPolygonTemp = PPolygonTemp -> Pnext;
  330.             PPolygonTemp -> Pnext = PObj -> U.Pl;
  331.             PObj -> U.Pl = PPolygon;
  332.         }
  333.         CagdSrfFreeList(Srfs);
  334.         
  335.         if (GlblGridFlag) {
  336.             RealType
  337.             Dx = BBox.Max[0] - BBox.Min[0],
  338.             Dy = BBox.Max[1] - BBox.Min[1],
  339.             Dz = BBox.Max[2] - BBox.Min[2],
  340.             M = MAX(MAX(Dx, Dy), Dz);
  341.             int IDx = (int) (GlblGridSize * (Dx / M)),
  342.             IDy = (int) (GlblGridSize * (Dy / M)),
  343.             IDz = (int) (GlblGridSize * (Dz / M));
  344.             
  345.             /* Save grid information derived from the surface bbox. */
  346.             sprintf(GridStr, "%d %d %d",
  347.                 IDx > 0 ? IDx : 1,
  348.                 IDy > 0 ? IDy : 1,
  349.                 IDz > 0 ? IDz : 1);
  350.             AttrSetObjectStrAttrib(PObj, "GridSize", GridStr);
  351.         }
  352.         }
  353.     }
  354.     }
  355.     
  356.     if (SrfObjs == NULL)
  357.     return CrvObjs;
  358.     else if (CrvObjs == NULL)
  359.         return SrfObjs;
  360.     else {
  361.     for (PObj = SrfObjs; PObj -> Pnext != NULL; PObj = PObj -> Pnext);
  362.     PObj -> Pnext = CrvObjs;
  363.     return SrfObjs;
  364.     }
  365. }
  366.  
  367. /*****************************************************************************
  368. * Dumps the data for ray shade.                             *
  369. *****************************************************************************/
  370. static void DumpDataForRayShade(IPObjectStruct *PObjects)
  371. {
  372.     static char *Header1[] = {
  373.     "/*",
  374.     " * This file was automatically created from IRIT solid modeller data",
  375.     " * using Irit2ray - IRIT to RayShade filter.",
  376.     " *",
  377.     " *            (c) Copyright 1991/92 Gershon Elber, Non commercial use only.",
  378.     " */",
  379.     "",
  380.     NULL
  381.     };
  382.     static char *Header2[] = {
  383.     "",
  384.     "eyep   0  0 10",
  385.     "lookp  0  0  0",
  386.     "up     0  1  0",
  387.     "fov 12",
  388.     "",
  389.     "light 1 1 1 point 10 30 10",
  390.     "",
  391.     NULL
  392.     };
  393.     int i,
  394.     TotalPolys = 0;
  395.     char Line[128];
  396.     IPObjectStruct *PObj,
  397.     *PObjHead = NULL;
  398.     FILE *FGeom, *FRay;
  399.  
  400.     sprintf(Line, "%s.ray", GlblOutFileName);
  401.     if (!GlblDumpOnlyGeometry) {
  402.     if ((FRay = fopen(Line, "w")) == NULL) {
  403.         fprintf(stderr, "Failed to open \"%s\".\n", Line);
  404.         Irit2RayExit(2);
  405.     }
  406.     }
  407.     else
  408.     FRay = NULL;
  409.  
  410.     sprintf(Line, "%s.geom", GlblOutFileName);
  411.     if ((FGeom = fopen(Line, "w")) == NULL) {
  412. #    if defined(OS2GCC) || defined(__WINNT__)
  413.         sprintf(Line, "%s.geo", GlblOutFileName);
  414.         if ((FGeom = fopen(Line, "w")) == NULL)
  415. #    endif /* OS2GCC || __WINNT__ */
  416.         {
  417.         fprintf(stderr, "Failed to open \"%s\".\n", Line);
  418.         Irit2RayExit(2);
  419.         }
  420.     }
  421.  
  422.     if (FRay != NULL)
  423.     for (i = 0; Header1[i] != NULL; i++)
  424.         fprintf(FRay, "%s\n", Header1[i]);
  425.     for (i = 0; Header1[i] != NULL; i++)
  426.     fprintf(FGeom, "%s\n", Header1[i]);
  427.  
  428.     /* Reverse object list since it was loaded in reverse by iritprsr module.*/
  429.     while (PObjects != NULL) {
  430.     PObj = PObjects;
  431.     PObjects = PObjects -> Pnext;
  432.     PObj -> Pnext = PObjHead;
  433.     PObjHead = PObj;
  434.     }
  435.     PObjects = PObjHead;
  436.  
  437.     while (PObjects) {
  438.     TotalPolys += DumpOneObject(FRay, FGeom, PObjects);
  439.     PObjects = PObjects -> Pnext;
  440.     }
  441.  
  442.     if (FRay != NULL) {
  443.     fprintf(FRay, "#include \"%s\"\n", Line);
  444.     for (i = 0; Header2[i] != NULL; i++)
  445.         fprintf(FRay, "%s\n", Header2[i]);
  446.     fclose(FRay);
  447.     }
  448.  
  449.     fclose(FGeom);
  450.  
  451.     fprintf(stderr, "\nTotal number of polygons - %d\n", TotalPolys);
  452. }
  453.  
  454. /*****************************************************************************
  455. * Routine to dump one object PObject.                         *
  456. *****************************************************************************/
  457. static int DumpOneObject(FILE *FRay, FILE *FGeom, IPObjectStruct *PObject)
  458. {
  459.     static int
  460.     ObjectSeqNum = 1;
  461.     static char
  462.         *StrAttribs[] = {
  463.     "specpow",
  464.     "reflect",
  465.     "transp",
  466.     "body",
  467.     "index",
  468.     NULL
  469.     };
  470.     int i, j, Color, RGBIColor[3],
  471.         PolyCount = 0,
  472.     HasColor = FALSE,
  473.     HasSrfProp = FALSE;
  474.     char *p, Name[LINE_LEN], SrfPropString[LINE_LEN_LONG];
  475.     RealType RGBColor[3],
  476.     Width = DEFAULT_POLYLINE_WIDTH;
  477.     IPPolygonStruct *PList;
  478.  
  479.     if (!IP_IS_POLY_OBJ(PObject) || !IP_IS_POLYGON_OBJ(PObject))
  480.     return 0;
  481.  
  482.     PList = PObject -> U.Pl;
  483.  
  484.     if (strlen(PObject -> Name) == 0)
  485.     sprintf(Name, "ObjSeq%d", ObjectSeqNum);
  486.     else
  487.     strcpy(Name, PObject -> Name);
  488.  
  489.     SrfPropString[0] = 0;
  490.     for (i = 0; StrAttribs[i] != NULL; i++) {
  491.     if ((p = AttrGetObjectStrAttrib(PObject, StrAttribs[i])) != NULL) {
  492.         strcat(SrfPropString, StrAttribs[i]);
  493.         strcat(SrfPropString, " ");
  494.         strcat(SrfPropString, p);
  495.         strcat(SrfPropString, " ");
  496.         HasSrfProp = TRUE;
  497.     }
  498.     }
  499.  
  500.     if (GlblDumpPolylines) {
  501.     if ((Width = AttrGetObjectRealAttrib(PObject, "Width")) >
  502.                                 IP_ATTR_BAD_REAL)
  503.         Width = DEFAULT_POLYLINE_WIDTH;
  504.     }
  505.  
  506.     if (GlblGridFlag) {
  507.     char
  508.         *GridStr = AttrGetObjectStrAttrib(PObject, "GridSize");
  509.  
  510.     if (GridStr != NULL)
  511.         fprintf(FGeom, "name %s%s grid %s\n",
  512.             GlblDumpObjsAsPolylines ? "Pl" : "", Name, GridStr);
  513.     else
  514.         fprintf(FGeom, "name %s%s grid %d %d %d\n",
  515.             GlblDumpObjsAsPolylines ? "Pl" : "", Name,
  516.             GlblGridSize, GlblGridSize, GlblGridSize);
  517.     }
  518.     else
  519.     fprintf(FGeom, "name %s%s list\n",
  520.         GlblDumpObjsAsPolylines ? "Pl" : "", Name);
  521.  
  522.     while (PList) {
  523.     PolyCount += DumpOnePoly(FGeom, PList, PObject, Name, Width);
  524.     PList =    PList -> Pnext;
  525.     }
  526.     fprintf(FGeom, "end\n");
  527.  
  528.     if (GlblTalkative)
  529.     fprintf(stderr, "Converting \"%s\" - %d triangles.\n",
  530.         Name, PolyCount);
  531.  
  532.     if (AttrGetObjectRGBColor(PObject,
  533.                   &RGBIColor[0], &RGBIColor[1], &RGBIColor[2])) {
  534.     HasColor = TRUE;
  535.     for (i = 0; i < 3; i++)
  536.         RGBColor[i] = RGBIColor[i];
  537.     }
  538.     else if ((Color = AttrGetObjectColor(PObject)) != IP_ATTR_NO_COLOR) {
  539.     for (i = 0; TransColorTable[i][0] >= 0; i++) {
  540.         if (TransColorTable[i][0] == Color) {
  541.         HasColor = TRUE;
  542.         for (j = 0; j < 3; j++)
  543.             RGBColor[j] = TransColorTable[i][j+1];
  544.         break;
  545.         }
  546.     }
  547.     }
  548.  
  549.     if (HasColor || HasSrfProp) {
  550.     if (FRay != NULL) {
  551.         fprintf(FRay, "surface %s%sSrfProp\n",
  552.             GlblDumpObjsAsPolylines ? "Pl" : "", Name);
  553.         if (HasColor) {
  554.         for (i = 0; i < 3; i++)
  555.             RGBColor[i] /= 255.0;
  556.  
  557.         fprintf(FRay, "\tambient  %7.4lf %7.4lf %7.4lf\n",
  558.             0.1 * RGBColor[0],
  559.             0.1 * RGBColor[1],
  560.             0.1 * RGBColor[2]);
  561.         fprintf(FRay, "\tdiffuse  %7.4lf %7.4lf %7.4lf\n",
  562.             0.7 * RGBColor[0],
  563.             0.7 * RGBColor[1],
  564.             0.7 * RGBColor[2]);
  565.         fprintf(FRay, "\tspecular %7.4lf %7.4lf %7.4lf\n",
  566.             0.8, 0.8, 0.8);
  567.         }
  568.         if (HasSrfProp)
  569.         fprintf(FRay, "\t%s\n", SrfPropString);
  570.     }
  571.  
  572.     fprintf(FGeom, "object %s%sSrfProp %s%s",
  573.         GlblDumpObjsAsPolylines ? "Pl" : "", Name,
  574.         GlblDumpObjsAsPolylines ? "Pl" : "", Name);
  575.     }
  576.     else
  577.     fprintf(FGeom, "object %s%s",
  578.         GlblDumpObjsAsPolylines ? "Pl" : "", Name);
  579.  
  580.     if ((p = AttrGetObjectStrAttrib(PObject, "texture")) != NULL) {
  581.     if (FRay != NULL)
  582.         fprintf(FRay, "#define %s%sTEXTURE %s\n",
  583.             GlblDumpObjsAsPolylines ? "Pl" : "", Name, p);
  584.     fprintf(FGeom, " texture %s%sTEXTURE",
  585.         GlblDumpObjsAsPolylines ? "Pl" : "", Name);
  586.     }
  587.     fprintf(FGeom, "\n\n");
  588.     if (FRay != NULL)
  589.     fprintf(FRay, "\n\n");
  590.  
  591.     ObjectSeqNum++;
  592.  
  593.     return PolyCount;
  594. }
  595.  
  596. /*****************************************************************************
  597. * Routine to dump one poly, using global Matrix transform CrntViewMat.       *
  598. *****************************************************************************/
  599. static int DumpOnePoly(FILE *FGeom, IPPolygonStruct *PPoly,
  600.                IPObjectStruct *PObj, char *Name, RealType Width)
  601. {
  602.     if (IP_IS_POLYGON_OBJ(PObj)) {
  603.     if (GlblDumpObjsAsPolylines)
  604.         return DumpOnePolyline(FGeom, PPoly, Name, Width, FALSE);
  605.     else
  606.         return DumpOnePolygon(FGeom, PPoly, Name);
  607.     }
  608.     else if (IP_IS_POLYLINE_OBJ(PObj)) {
  609.     return DumpOnePolyline(FGeom, PPoly, Name, Width, TRUE);
  610.     }
  611.     else
  612.     return 0;
  613. }
  614.  
  615. /*****************************************************************************
  616. * Routine to dump one polygon, using global Matrix transform CrntViewMat.    *
  617. *****************************************************************************/
  618. static int DumpOnePolygon(FILE *FGeom, IPPolygonStruct *PPolygon, char *Name)
  619. {
  620.     int i,
  621.     TriCount = 0;
  622.     RealType *MappedNormal[3], *MappedPoint[3], Normal[3], Vec1[3], Vec2[3];
  623.     IPVertexStruct *VFirst, *V1, *V2,
  624.     *VList = PPolygon -> PVertex;
  625.  
  626.     if (VList == NULL)
  627.     return 0;
  628.  
  629.     if (!IritPrsrIsConvexPolygon(PPolygon)) {
  630.     static int
  631.         Printed = FALSE;
  632.  
  633.     if (!Printed) {
  634.         fprintf(stderr,
  635.             "\nWARNING: Non convex polygon(s) might be in data (see CONVEX in IRIT),\n\t\t\t\toutput can be wrong as the result!\n");
  636.         Printed = TRUE;
  637.     }
  638.     }
  639.  
  640.     VFirst = VList;
  641.     V1 = VFirst -> Pnext;
  642.     V2 = V1 -> Pnext;
  643.     
  644.     while (V2 != NULL) {
  645.     MappedPoint[0] = MapPoint(VFirst -> Coord);
  646.     MappedPoint[1] = MapPoint(V1 -> Coord);
  647.     MappedPoint[2] = MapPoint(V2 -> Coord);
  648.     
  649.     /* Test for two type of degeneracies. Make sure that no two  */
  650.     /* points in the triangle are the same and that they are     */
  651.     /* not colinear.                         */
  652.     if (!PT_APX_EQ(MappedPoint[0], MappedPoint[1]) &&
  653.         !PT_APX_EQ(MappedPoint[0], MappedPoint[2]) &&
  654.         !PT_APX_EQ(MappedPoint[1], MappedPoint[2])) {
  655.         
  656.         PT_SUB(Vec1, MappedPoint[0], MappedPoint[1]);
  657.         PT_SUB(Vec2, MappedPoint[1], MappedPoint[2]);
  658.         PT_NORMALIZE(Vec1);
  659.         PT_NORMALIZE(Vec2);
  660.         CROSS_PROD(Normal, Vec1, Vec2);
  661.         
  662.         if (PT_LENGTH(Normal) > SIZE_EPSILON) {
  663.         PT_NORMALIZE(Normal);
  664.         
  665.         MappedNormal[0] =
  666.             MapVector(VFirst -> Coord, VFirst -> Normal);
  667.         MappedNormal[1] =
  668.             MapVector(V1 -> Coord, V1 -> Normal);
  669.         MappedNormal[2] =
  670.             MapVector(V2 -> Coord, V2 -> Normal);
  671.         
  672.         if (DOT_PROD(Normal, MappedNormal[0]) < -SIZE_EPSILON ||
  673.             DOT_PROD(Normal, MappedNormal[1]) < -SIZE_EPSILON ||
  674.             DOT_PROD(Normal, MappedNormal[2]) < -SIZE_EPSILON) {
  675.             SWAP(RealType *, MappedPoint[1], MappedPoint[2]);
  676.             SWAP(RealType *, MappedNormal[1], MappedNormal[2]);
  677.             PT_SCALE(Normal, -1.0);
  678.         }
  679.         
  680.         /* Make sure all normals are set properly: */
  681.         if (DOT_PROD(MappedNormal[0], MappedNormal[0]) < SIZE_EPSILON)
  682.             PT_COPY(MappedNormal[0], Normal);
  683.         if (DOT_PROD(MappedNormal[1], MappedNormal[1]) < SIZE_EPSILON)
  684.             PT_COPY(MappedNormal[1], Normal);
  685.         if (DOT_PROD(MappedNormal[2], MappedNormal[2]) < SIZE_EPSILON)
  686.             PT_COPY(MappedNormal[2], Normal);
  687.         
  688.         TriCount++;
  689.         
  690.         for (i = 0; i < 3; i++)
  691.             fprintf(FGeom,
  692.                 "%s %10.7lf %10.7lf %10.7lf  %9.6lf %9.6lf %9.6lf\n",
  693.                 i == 0 ? "    triangle" : "\t    ",
  694.                 MappedPoint[i][0],
  695.                 MappedPoint[i][1],
  696.                 MappedPoint[i][2],
  697.                 MappedNormal[i][0],
  698.                 MappedNormal[i][1],
  699.                 MappedNormal[i][2]);
  700.         }
  701.     }
  702.     
  703.     V1 = V2;
  704.     V2 = V2 -> Pnext;
  705.     }
  706.  
  707.     return TriCount;
  708. }
  709.  
  710. /*****************************************************************************
  711. * Routine to dump one polyline, using global Matrix transform CrntViewMat.   *
  712. *****************************************************************************/
  713. static int DumpOnePolyline(FILE *FGeom, IPPolygonStruct *PPolyline, char *Name,
  714.                         RealType Width, int IsPolyline)
  715. {
  716.     int DumpedSphere = FALSE;
  717.     RealType *MappedPoint[2];
  718.     IPVertexStruct *V1, *V2,
  719.     *VList = PPolyline -> PVertex;
  720.  
  721.     if (!GlblDumpPolylines || VList == NULL)
  722.     return 0;
  723.  
  724.     V1 = VList;
  725.     V2 = V1 -> Pnext;
  726.     
  727.     while (V2 != NULL) {
  728.     MappedPoint[0] = MapPoint(V1 -> Coord);
  729.     MappedPoint[1] = MapPoint(V2 -> Coord);
  730.  
  731.     if (GlblZBBox[1] < MappedPoint[0][2])
  732.         GlblZBBox[1] = MappedPoint[0][2];
  733.     if (GlblZBBox[0] > MappedPoint[0][2])
  734.         GlblZBBox[0] = MappedPoint[0][2];
  735.  
  736.     if (!PT_APX_EQ(MappedPoint[0], MappedPoint[1]) &&
  737.         (IsPolyline || !IP_IS_INTERNAL_VRTX(V1))) {
  738.         DumpCone(Width * MAX(MappedPoint[0][2] - GlblPolylineDepthCue[0],
  739.                  MIN_RATIO) / GlblPolylineDepthCue[2],
  740.              MappedPoint[0][0],
  741.              MappedPoint[0][1],
  742.              MappedPoint[0][2],
  743.              Width * MAX(MappedPoint[1][2] - GlblPolylineDepthCue[0],
  744.                  MIN_RATIO) / GlblPolylineDepthCue[2],
  745.              MappedPoint[1][0],
  746.              MappedPoint[1][1],
  747.              MappedPoint[1][2],
  748.              FGeom, Name);
  749.  
  750.         if (!DumpedSphere)
  751.         fprintf(FGeom,
  752.             "sphere %s%sSrfProp %7.5lf %7.5lf %7.5lf %7.5lf\n",
  753.             GlblDumpObjsAsPolylines ? "Pl" : "", Name,
  754.             Width * MAX(MappedPoint[0][2] - GlblPolylineDepthCue[0],
  755.                     MIN_RATIO) / GlblPolylineDepthCue[2],
  756.             MappedPoint[0][0],
  757.             MappedPoint[0][1],
  758.             MappedPoint[0][2]);
  759.         fprintf(FGeom,
  760.             "sphere %s%sSrfProp %7.5lf %7.5lf %7.5lf %7.5lf\n",
  761.             GlblDumpObjsAsPolylines ? "Pl" : "", Name,
  762.             Width * MAX(MappedPoint[1][2] - GlblPolylineDepthCue[0],
  763.                 MIN_RATIO) / GlblPolylineDepthCue[2],
  764.             MappedPoint[1][0],
  765.             MappedPoint[1][1],
  766.             MappedPoint[1][2]);
  767.         DumpedSphere = TRUE;
  768.     }
  769.     else {
  770.         DumpedSphere = FALSE;
  771.     }
  772.     
  773.     V1 = V2;
  774.     V2 = V2 -> Pnext;
  775.     }
  776.  
  777.     if (!IsPolyline && !IP_IS_INTERNAL_VRTX(V1)) {
  778.     MappedPoint[0] = MapPoint(V1 -> Coord);
  779.     MappedPoint[1] = MapPoint(VList -> Coord);
  780.  
  781.     if (!PT_APX_EQ(MappedPoint[0], MappedPoint[1])) {
  782.         DumpCone(Width * MAX(MappedPoint[0][2] - GlblPolylineDepthCue[0],
  783.                  MIN_RATIO) / GlblPolylineDepthCue[2],
  784.              MappedPoint[0][0],
  785.              MappedPoint[0][1],
  786.              MappedPoint[0][2],
  787.              Width * MAX(MappedPoint[1][2] - GlblPolylineDepthCue[0],
  788.                  MIN_RATIO) / GlblPolylineDepthCue[2],
  789.              MappedPoint[1][0],
  790.              MappedPoint[1][1],
  791.              MappedPoint[1][2],
  792.              FGeom, Name);
  793.  
  794.         if (!DumpedSphere)
  795.         fprintf(FGeom,
  796.             "sphere %s%sSrfProp %7.5lf %7.5lf %7.5lf %7.5lf\n",
  797.             GlblDumpObjsAsPolylines ? "Pl" : "", Name,
  798.             Width * MAX(MappedPoint[0][2] - GlblPolylineDepthCue[0],
  799.                     MIN_RATIO) / GlblPolylineDepthCue[2],
  800.             MappedPoint[0][0],
  801.             MappedPoint[0][1],
  802.             MappedPoint[0][2]);
  803.         fprintf(FGeom,
  804.             "sphere %s%sSrfProp %7.5lf %7.5lf %7.5lf %7.5lf\n",
  805.             GlblDumpObjsAsPolylines ? "Pl" : "", Name,
  806.             Width * MAX(MappedPoint[1][2] - GlblPolylineDepthCue[0],
  807.                 MIN_RATIO) / GlblPolylineDepthCue[2],
  808.             MappedPoint[1][0],
  809.             MappedPoint[1][1],
  810.             MappedPoint[1][2]);
  811.     }
  812.     }
  813.  
  814.     return 1;
  815. }
  816.  
  817. /*****************************************************************************
  818. *   Routine to dump a cone (can degenerate to a cylinder or nothing).         *
  819. *****************************************************************************/
  820. static void DumpCone(RealType R1, RealType X1, RealType Y1, RealType Z1,
  821.              RealType R2, RealType X2, RealType Y2, RealType Z2,
  822.              FILE *FGeom, char *Name)
  823. {
  824.     RealType
  825.     Len = sqrt(SQR(X1 - X2) + SQR(Y1 - Y2) + SQR(Z1 - Z2));
  826.  
  827.     if (Len < CONE_SIZE)
  828.     return;
  829.  
  830.     if (ABS(R1 - R2) < CONE_SIZE) {
  831.     fprintf(FGeom,
  832.         "cylinder %s%sSrfProp %7.5lf  %7.5lf %7.5lf %7.5lf  %7.5lf %7.5lf %7.5lf\n",
  833.         GlblDumpObjsAsPolylines ? "Pl" : "", Name,
  834.         R1, X1, Y1, Z1, X2, Y2, Z2);
  835.     }
  836.     else {
  837.     fprintf(FGeom,
  838.         "cone %s%sSrfProp %7.5lf %7.5lf %7.5lf %7.5lf  %7.5lf %7.5lf %7.5lf %7.5lf\n",
  839.         GlblDumpObjsAsPolylines ? "Pl" : "", Name,
  840.         R1, X1, Y1, Z1, R2, X2, Y2, Z2);
  841.     }
  842. }
  843.  
  844. /*****************************************************************************
  845. * Maps the given E3 point using the CrntViewMat.                 *
  846. *****************************************************************************/
  847. static RealType *MapPoint(RealType *Pt)
  848. {
  849.     static int Count = 0;
  850.     static RealType MappedPts[3][3];
  851.     RealType *MappedPt = MappedPts[Count++];
  852.  
  853.     if (Count >= 3)
  854.     Count = 0;
  855.  
  856.     MatMultVecby4by4(MappedPt, Pt, CrntViewMat);
  857.  
  858.     return MappedPt;
  859. }
  860.  
  861. /*****************************************************************************
  862. * Maps the given E3 vector using the CrntViewMat.                 *
  863. * This routine will return a zero vector if normal is not computable.         *
  864. *****************************************************************************/
  865. static RealType *MapVector(RealType *Pt, RealType *Vec)
  866. {
  867.     static int
  868.     Count = 0,
  869.     WasWarning = 0;
  870.     static RealType MappedVecs[3][3];
  871.     RealType MappedPt[3], Pt2[3], MappedPt2[3],
  872.     *MappedVec = MappedVecs[Count++];
  873.  
  874.     if (Count >= 3)
  875.     Count = 0;
  876.  
  877.     if (DOT_PROD(Vec, Vec) < SIZE_EPSILON) {
  878.     MappedVec[0] = MappedVec[1] = MappedVec[2] = 0.0;
  879.     if (!WasWarning) {
  880.         WasWarning = 1;
  881.         fprintf(stderr, "Non computable normals detected. Approximated from geometry.\n");
  882.     }
  883.     }
  884.     else {
  885.         MatMultVecby4by4(MappedPt, Pt, CrntViewMat);
  886.  
  887.         PT_ADD(Pt2, Pt, Vec);
  888.         MatMultVecby4by4(MappedPt2, Pt2, CrntViewMat);
  889.  
  890.         PT_SUB(MappedVec, MappedPt2, MappedPt);
  891.         PT_NORMALIZE(MappedVec);
  892.     }
  893.  
  894.     return MappedVec;
  895. }
  896.  
  897. /*****************************************************************************
  898. * Irit2Ray exit routine.                              *
  899. *****************************************************************************/
  900. static void Irit2RayExit(int ExitCode)
  901. {
  902.     exit(ExitCode);
  903. }
  904.